'''Contains all the event handler functions for the dell package GUIs.'''
import PySimpleGUI as sg
from warranty_manager.gui.chromebook_notes import get_chromebook_note_gui
from warranty_manager.gui.get_items import select_part, get_notes_gui
from warranty_manager.gui.confirmation import get_confirmation
from warranty_manager.claim.common import choose_note_type
from warranty_manager.claim.dell.dispatch_api import (
    get_part_number_from_description, get_part_numbers_dictionary
)


def handle_load_parts(window):
    '''
    Handles the event that loads the part descriptions and numbers dictionary
    from a JSON file, for the request_creator and request_submitter GUIs.
    '''
    if get_confirmation('load the specified part descriptions and numbers dictionary'):
        part_nums_dict = get_part_numbers_dictionary()

        if part_nums_dict:
            window['-LOAD_PARTS-'].update('Load Other Parts')
            sg.popup(
                'The dictionary of part descriptions and numbers has been successfully added!',
                title='Success'
            )
            return part_nums_dict

        return {}


def handle_add_part(window, part_nums_dict, parts_list):
    '''
    Handles the event that adds a part number and (optionally) PPID
    to the request_creator and request_submitter GUIs.
    '''
    if not part_nums_dict:
        sg.popup_error(
            'You must load a dictionary of part descriptions and numbers, '
            'in order to add a part!',
            title='Error'
        )
        return False
    # To make sure that no more than four parts are added
    elif len(parts_list) == 4:
        sg.popup_error(
            'You cannot have more than four parts per request!',
            title='Error'
        )
        return False
    else:
        part_num, ppid = get_part_number_from_description(part_nums_dict)

        if part_num and not ppid:
            parts_list.append({'PN': part_num, 'PPID': None})
        elif part_num and ppid:

            if len(ppid) != 20:
                sg.popup_error('The PPID must be 20 characters long!', title='Error')
                return False

            parts_list.append({'PN': part_num, 'PPID': ppid})
        # No part number entered
        else:
            return False

    if len(parts_list) > 0:
        window['-ADD_PART-'].update(f"Add Part ({len(parts_list)})")


def handle_view_parts(parts_list):
    '''
    Handles the event that displays all added part numbers and PPIDs,
    for the request_creator and request_submitter GUIs.
    '''
    if len(parts_list) == 0:
        sg.popup('There are no parts to view!', title='Info')
    else:
        view_string = ''

        for part in parts_list:
            view_string += f"Part Number: {part['PN']}, PPID: {part['PPID']}\n"

        sg.popup(view_string, title='Info')


def handle_replace_parts(window, part_nums_dict, parts_list):
    '''
    Handles the event that replaces one list of part numbers and PPIDs with a new list,
    for the request_creator and request_submitter GUIs.
    '''
    if len(parts_list) == 0:
        sg.popup('There are no parts to replace!', title='Info')
    else:
        if get_confirmation('replace all current parts and PPIDs with a new list of parts'):
            parts_list.clear()
            handle_add_part(window, part_nums_dict, parts_list)


def handle_remove_part(window, parts_list):
    '''
    Handles the event that removes a part number and PPID from
    the request_creator and request_submitter GUIs.
    '''
    if len(parts_list) == 0:
        sg.popup('There are no parts to remove!', title='Info')
    else:
        part_to_remove = select_part(parts_list)

        if part_to_remove and get_confirmation(
                f"remove part number '{part_to_remove['PN']}', "
                f"and its associated PPID, '{part_to_remove['PPID']}' from the request"):
            parts_list.remove(part_to_remove)

            if len(parts_list) == 0:
                window['-ADD_PART-'].update('Add Part')
            else:
                window['-ADD_PART-'].update(f"Add Part ({len(parts_list)})")


def validate_note(note):
    '''
    Checks to see whether or not the problem/troubleshooting note for the request
    creator and request_resubmitter GUIs is more than 1,000 characters long,
    which is the upper limit for Dispatch API requests.
    '''
    if len(note) <= 1000:
        return note
    else:
        sg.popup_error(
            'The problem/troubleshooting note cannot be more than 1,000 characters long.\n'
            'Please enter a shorter note.',
            title='Error'
        )
        return ''


def handle_add_note(window, note):
    '''
    Handles the event that adds a problem/troubleshooting note
    to the request_creator and request_submitter GUIs.
    '''
    note = ''
    note_type = choose_note_type()

    if note_type == 'Chromebook':
        try:
            description, troubleshooting = get_chromebook_note_gui()
            note += f'{description} {troubleshooting} '
        except TypeError: # Chromebook issue GUI window was closed
            return ''
    elif note_type == 'Non-Chromebook':
        notes_to_add = get_notes_gui()

        if len(notes_to_add) > 0:
            note += ' '.join(notes_to_add) + ' '

    else:
        return note

    if len(note) > 0:
        window['-ADD_NOTE-'].update('Add To Note')

    return validate_note(note)


def handle_view_note(note):
    '''
    Handles the event that displays the current note, for the request_creator
    and request_submitter GUIs.
    '''
    if len(note) == 0:
        sg.popup('There is no note to view!', title='Info')
    else:
        sg.popup(note, title='Info')


def validate_common(values):
    '''
    Validates the Dell TechDirect username and password fields aren't empty,
    and sets the sandbox value for all dell package GUI modules.
    '''
    username = values['-UN-'].strip()
    password = values['-PW-'].strip()

    if username and password:
        if not values['-SANDBOX-']:
            sandbox = False
        else:
            sandbox = True

        return (username, password, sandbox)
    else:
        sg.popup_error('You must enter a username and password!', title='Error')


def validate_resubmitted_request(values, request_info=None):
    '''
    Validates that the dispatch code, username, password, and sandbox value
    are correctly filled in, for the request_resubmitter GUI.
    '''
    try:
        username, password, sandbox = validate_common(values)
    except TypeError:
        return False
    else:
        dispatch_code = values['-CODE-'].strip()

        if not dispatch_code:
            sg.popup_error('You must enter a dispatch code!', title='Error')
        elif request_info:

            if not request_info['note']:
                sg.popup_error('You must add at least one note!', title='Error')
            elif len(request_info['parts']) == 0:
                sg.popup_error(
                    'You must add at least one part!',
                    title='Error'
                )
            else:
                return (username, password, dispatch_code, sandbox)

        else:
            return (username, password, dispatch_code, sandbox)


def validate_part_finder(values, is_tag=False, is_type=False):
    '''
    Validates that the either service tag or device type field is not empty,
    depending on which button is clicked in the part_finder GUI.
    '''
    try:
        username, password, sandbox = validate_common(values)
    except TypeError:
        return False
    else:
        tag = values['-TAG-'].strip()
        device_type = values['-TYPE-'].strip()

        if is_tag and not tag:
            sg.popup_error(
                'You must enter a service tag to get the parts!',
                title='Error'
            )
        elif is_type and not device_type:
            sg.popup_error(
                'You must enter a device type to get the parts!',
                title='Error'
            )
        elif is_tag and tag:
            return (username, password, tag, sandbox)
        elif is_type and device_type:
            return (username, password, device_type, sandbox)
        else:
            return None
